<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD><TITLE>tsv manual page - Threading</TITLE>
<link rel="stylesheet" href="../docs.css" type="text/css" media="all">
</HEAD>
<BODY><H2><a href="../contents.htm">Tcl8.6.11/Tk8.6.11 Documentation</a> <small>&gt;</small> <a href="contents.htm">Thread Package Commands, version 2.8.6</a> <small>&gt;</small> tsv</H2>
<H3><A HREF="../UserCmd/contents.htm">Tcl/Tk Applications</A> | <A HREF="../TclCmd/contents.htm">Tcl Commands</A> | <A HREF="../TkCmd/contents.htm">Tk Commands</A> | <A HREF="../ItclCmd/contents.htm">[incr Tcl] Package Commands</A> | <A HREF="../SqliteCmd/contents.htm">SQLite3 Package Commands</A> | <A HREF="../TdbcCmd/contents.htm">TDBC Package Commands</A> | <A HREF="../TdbcmysqlCmd/contents.htm">tdbc::mysql Package Commands</A> | <A HREF="../TdbcodbcCmd/contents.htm">tdbc::odbc Package Commands</A> | <A HREF="../TdbcpostgresCmd/contents.htm">tdbc::postgres Package Commands</A> | <A HREF="../TdbcsqliteCmd/contents.htm">tdbc::sqlite3 Package Commands</A> | <A HREF="../ThreadCmd/contents.htm">Thread Package Commands</A> | <A HREF="../TclLib/contents.htm">Tcl C API</A> | <A HREF="../TkLib/contents.htm">Tk C API</A> | <A HREF="../ItclLib/contents.htm">[incr Tcl] Package C API</A> | <A HREF="../TdbcLib/contents.htm">TDBC Package C API</A></H3>
<DL>
<DD><A HREF="tsv.htm#M2" NAME="L69">NAME</A>
<DL><DD>tsv &mdash; Part of the Tcl threading extension allowing script level manipulation of data shared between threads .</DD></DL>
<DD><A HREF="tsv.htm#M3" NAME="L70">SYNOPSIS</A>
<DL>
</DL>
<DD><A HREF="tsv.htm#M4" NAME="L71">DESCRIPTION</A>
<DD><A HREF="tsv.htm#M5" NAME="L72">ELEMENT COMMANDS</A>
<DL class="element commands">
<DD><A HREF="tsv.htm#M6" NAME="L73"><B>tsv::names</B> ?pattern?</A>
<DD><A HREF="tsv.htm#M7" NAME="L74"><B>tsv::object</B> <I>varname</I> <I>element</I></A>
<DD><A HREF="tsv.htm#M8" NAME="L75"><B>tsv::set</B> <I>varname</I> <I>element</I> ?value?</A>
<DD><A HREF="tsv.htm#M9" NAME="L76"><B>tsv::get</B> <I>varname</I> <I>element</I> ?namedvar?</A>
<DD><A HREF="tsv.htm#M10" NAME="L77"><B>tsv::unset</B> <I>varname</I> ?element?</A>
<DD><A HREF="tsv.htm#M11" NAME="L78"><B>tsv::exists</B> <I>varname</I> <I>element</I></A>
<DD><A HREF="tsv.htm#M12" NAME="L79"><B>tsv::pop</B> <I>varname</I> <I>element</I></A>
<DD><A HREF="tsv.htm#M13" NAME="L80"><B>tsv::move</B> <I>varname</I> <I>oldname</I> <I>newname</I></A>
<DD><A HREF="tsv.htm#M14" NAME="L81"><B>tsv::incr</B> <I>varname</I> <I>element</I> ?count?</A>
<DD><A HREF="tsv.htm#M15" NAME="L82"><B>tsv::append</B> <I>varname</I> <I>element</I> <I>value</I> ?value 	.	.	.?</A>
<DD><A HREF="tsv.htm#M16" NAME="L83"><B>tsv::lock</B> <I>varname</I> <I>arg</I> ?arg 	.	.	.?</A>
<DD><A HREF="tsv.htm#M17" NAME="L84"><B>tsv::handlers</B></A>
</DL>
<DD><A HREF="tsv.htm#M18" NAME="L85">LIST COMMANDS</A>
<DL class="list commands">
<DD><A HREF="tsv.htm#M19" NAME="L86"><B>tsv::lappend</B> <I>varname</I> <I>element</I> <I>value</I> ?value 	.	.	.?</A>
<DD><A HREF="tsv.htm#M20" NAME="L87"><B>tsv::linsert</B> <I>varname</I> <I>element</I> <I>index</I> <I>value</I> ?value 	.	.	.?</A>
<DD><A HREF="tsv.htm#M21" NAME="L88"><B>tsv::lreplace</B> <I>varname</I> <I>element</I> <I>first</I> <I>last</I> ?value 	.	.	.?</A>
<DD><A HREF="tsv.htm#M22" NAME="L89"><B>tsv::llength</B> <I>varname</I> <I>element</I></A>
<DD><A HREF="tsv.htm#M23" NAME="L90"><B>tsv::lindex</B> <I>varname</I> <I>element</I> ?index?</A>
<DD><A HREF="tsv.htm#M24" NAME="L91"><B>tsv::lrange</B> <I>varname</I> <I>element</I> <I>from</I> <I>to</I></A>
<DD><A HREF="tsv.htm#M25" NAME="L92"><B>tsv::lsearch</B> <I>varname</I> <I>element</I> ?options? <I>pattern</I></A>
<DD><A HREF="tsv.htm#M26" NAME="L93"><B>tsv::lset</B> <I>varname</I> <I>element</I> <I>index</I> ?index 	.	.	.? <I>value</I></A>
<DD><A HREF="tsv.htm#M27" NAME="L94"><B>tsv::lpop</B> <I>varname</I> <I>element</I> ?index?</A>
<DD><A HREF="tsv.htm#M28" NAME="L95"><B>tsv::lpush</B> <I>varname</I> <I>element</I> ?index?</A>
</DL>
<DD><A HREF="tsv.htm#M29" NAME="L96">ARRAY COMMANDS</A>
<DL class="array commands">
<DD><A HREF="tsv.htm#M30" NAME="L97"><B>tsv::array set</B> <I>varname</I> <I>list</I></A>
<DD><A HREF="tsv.htm#M31" NAME="L98"><B>tsv::array get</B> <I>varname</I> ?pattern?</A>
<DD><A HREF="tsv.htm#M32" NAME="L99"><B>tsv::array names</B> <I>varname</I> ?pattern?</A>
<DD><A HREF="tsv.htm#M33" NAME="L100"><B>tsv::array size</B> <I>varname</I></A>
<DD><A HREF="tsv.htm#M34" NAME="L101"><B>tsv::array reset</B> <I>varname</I> <I>list</I></A>
<DD><A HREF="tsv.htm#M35" NAME="L102"><B>tsv::array bind</B> <I>varname</I> <I>handle</I></A>
<DD><A HREF="tsv.htm#M36" NAME="L103"><B>tsv::array unbind</B> <I>varname</I></A>
<DD><A HREF="tsv.htm#M37" NAME="L104"><B>tsv::array isbound</B> <I>varname</I></A>
</DL>
<DD><A HREF="tsv.htm#M38" NAME="L105">KEYED LIST COMMANDS</A>
<DL class="keyed list commands">
<DD><A HREF="tsv.htm#M39" NAME="L106"><B>tsv::keyldel</B> <I>varname</I> <I>keylist</I> <I>key</I></A>
<DD><A HREF="tsv.htm#M40" NAME="L107"><B>tsv::keylget</B> <I>varname</I> <I>keylist</I> <I>key</I> ?retvar?</A>
<DD><A HREF="tsv.htm#M41" NAME="L108"><B>tsv::keylkeys</B> <I>varname</I> <I>keylist</I> ?key?</A>
<DD><A HREF="tsv.htm#M42" NAME="L109"><B>tsv::keylset</B> <I>varname</I> <I>keylist</I> <I>key</I> <I>value</I> ?key value	.	.?</A>
</DL>
<DD><A HREF="tsv.htm#M43" NAME="L110">DISCUSSION</A>
<DD><A HREF="tsv.htm#M44" NAME="L111">CREDITS</A>
<DD><A HREF="tsv.htm#M45" NAME="L112">SEE ALSO</A>
<DD><A HREF="tsv.htm#M46" NAME="L113">KEYWORDS</A>
</DL>
<H3><A NAME="M2">NAME</A></H3>
tsv &mdash; Part of the Tcl threading extension allowing script level manipulation of data shared between threads .
<H3><A NAME="M3">SYNOPSIS</A></H3>
package require <B>Tcl  8	.4</B><BR>
package require <B>Thread  ?2	.8?</B><BR>
<B>tsv::names</B> ?pattern?<BR>
<B>tsv::object</B> <I>varname</I> <I>element</I><BR>
<B>tsv::set</B> <I>varname</I> <I>element</I> ?value?<BR>
<B>tsv::get</B> <I>varname</I> <I>element</I> ?namedvar?<BR>
<B>tsv::unset</B> <I>varname</I> ?element?<BR>
<B>tsv::exists</B> <I>varname</I> <I>element</I><BR>
<B>tsv::pop</B> <I>varname</I> <I>element</I><BR>
<B>tsv::move</B> <I>varname</I> <I>oldname</I> <I>newname</I><BR>
<B>tsv::incr</B> <I>varname</I> <I>element</I> ?count?<BR>
<B>tsv::append</B> <I>varname</I> <I>element</I> <I>value</I> ?value 	.	.	.?<BR>
<B>tsv::lock</B> <I>varname</I> <I>arg</I> ?arg 	.	.	.?<BR>
<B>tsv::handlers</B><BR>
<B>tsv::lappend</B> <I>varname</I> <I>element</I> <I>value</I> ?value 	.	.	.?<BR>
<B>tsv::linsert</B> <I>varname</I> <I>element</I> <I>index</I> <I>value</I> ?value 	.	.	.?<BR>
<B>tsv::lreplace</B> <I>varname</I> <I>element</I> <I>first</I> <I>last</I> ?value 	.	.	.?<BR>
<B>tsv::llength</B> <I>varname</I> <I>element</I><BR>
<B>tsv::lindex</B> <I>varname</I> <I>element</I> ?index?<BR>
<B>tsv::lrange</B> <I>varname</I> <I>element</I> <I>from</I> <I>to</I><BR>
<B>tsv::lsearch</B> <I>varname</I> <I>element</I> ?options? <I>pattern</I><BR>
<B>tsv::lset</B> <I>varname</I> <I>element</I> <I>index</I> ?index 	.	.	.? <I>value</I><BR>
<B>tsv::lpop</B> <I>varname</I> <I>element</I> ?index?<BR>
<B>tsv::lpush</B> <I>varname</I> <I>element</I> ?index?<BR>
<B>tsv::array set</B> <I>varname</I> <I>list</I><BR>
<B>tsv::array get</B> <I>varname</I> ?pattern?<BR>
<B>tsv::array names</B> <I>varname</I> ?pattern?<BR>
<B>tsv::array size</B> <I>varname</I><BR>
<B>tsv::array reset</B> <I>varname</I> <I>list</I><BR>
<B>tsv::array bind</B> <I>varname</I> <I>handle</I><BR>
<B>tsv::array unbind</B> <I>varname</I><BR>
<B>tsv::array isbound</B> <I>varname</I><BR>
<B>tsv::keyldel</B> <I>varname</I> <I>keylist</I> <I>key</I><BR>
<B>tsv::keylget</B> <I>varname</I> <I>keylist</I> <I>key</I> ?retvar?<BR>
<B>tsv::keylkeys</B> <I>varname</I> <I>keylist</I> ?key?<BR>
<B>tsv::keylset</B> <I>varname</I> <I>keylist</I> <I>key</I> <I>value</I> ?key value	.	.?<BR>
<H3><A NAME="M4">DESCRIPTION</A></H3>
This section describes commands implementing thread shared variables	.
A thread shared variable is very similar to a Tcl array but in
contrast to a Tcl array it is created in shared memory and can
be accessed from many threads at the same time	. Important feature of
thread shared variable is that each access to the variable is internaly
protected by a mutex so script programmer does not have to take care
about locking the variable himself	.
<P>
Thread shared variables are not bound to any thread explicitly	. That
means that when a thread which created any of thread shared variables
exits, the variable and associated memory is not unset/reclaimed	.
User has to explicitly unset the variable to reclaim the memory
consumed by the variable	.
<H3><A NAME="M5">ELEMENT COMMANDS</A></H3>
<DL class="element commands">
<DT><A NAME="M6"><B>tsv::names</B> ?pattern?</A><DD>
Returns names of shared variables matching optional ?pattern?
or all known variables if pattern is ommited	.
<P><DT><A NAME="M7"><B>tsv::object</B> <I>varname</I> <I>element</I></A><DD>
Creates object accessor command for the <I>element</I> in the
shared variable <I>varname</I>	. Using this command, one can apply most
of the other shared variable commands as method functions of
the element object command	. The object command is automatically
deleted when the element which this command is pointing to is unset	.
<PRE>% tsv::set foo bar &quot;A shared string&quot;
    % set string [tsv::object foo bar]
    % $string append &quot; appended&quot;
    =&gt; A shared string appended</PRE>
<P><DT><A NAME="M8"><B>tsv::set</B> <I>varname</I> <I>element</I> ?value?</A><DD>
Sets the value of the <I>element</I> in the shared variable <I>varname</I>
to <I>value</I> and returns the value to caller	. The <I>value</I>
may be ommited, in which case the command will return the current
value of the element	. If the element cannot be found, error is triggered	.
<P><DT><A NAME="M9"><B>tsv::get</B> <I>varname</I> <I>element</I> ?namedvar?</A><DD>
Retrieves the value of the <I>element</I> from the shared variable <I>varname</I>	.
If the optional argument <I>namedvar</I> is given, the value is
stored in the named variable	. Return value of the command depends
of the existence of the optional argument <I>namedvar</I>	.
If the argument is ommited and the requested element cannot be found
in the shared array, the command triggers error	. If, however, the
optional argument is given on the command line, the command returns
true (1) if the element is found or false (0) if the element is not found	.
<P><DT><A NAME="M10"><B>tsv::unset</B> <I>varname</I> ?element?</A><DD>
Unsets the <I>element</I> from the shared variable <I>varname</I>	.
If the optional element is not given, it deletes the variable	.
<P><DT><A NAME="M11"><B>tsv::exists</B> <I>varname</I> <I>element</I></A><DD>
Checks wether the <I>element</I> exists in the shared variable <I>varname</I>
and returns true (1) if it does or false (0) if it doesn't	.
<P><DT><A NAME="M12"><B>tsv::pop</B> <I>varname</I> <I>element</I></A><DD>
Returns value of the <I>element</I> in the shared variable <I>varname</I>
and unsets the element, all in one atomic operation	.
<P><DT><A NAME="M13"><B>tsv::move</B> <I>varname</I> <I>oldname</I> <I>newname</I></A><DD>
Renames the element <I>oldname</I> to the <I>newname</I> in the
shared variable <I>varname</I>	. This effectively performs an get/unset/set
sequence of operations but all in one atomic step	.
<P><DT><A NAME="M14"><B>tsv::incr</B> <I>varname</I> <I>element</I> ?count?</A><DD>
Similar to standard Tcl <B><A HREF="../TclCmd/incr.htm">incr</A></B> command but increments the value
of the <I>element</I> in shared variaboe <I>varname</I> instead of
the Tcl variable	.
<P><DT><A NAME="M15"><B>tsv::append</B> <I>varname</I> <I>element</I> <I>value</I> ?value 	.	.	.?</A><DD>
Similar to standard Tcl <B><A HREF="../TclCmd/append.htm">append</A></B> command but appends one or more
values to the <I>element</I> in shared variable <I>varname</I> instead of the
Tcl variable	.
<P><DT><A NAME="M16"><B>tsv::lock</B> <I>varname</I> <I>arg</I> ?arg 	.	.	.?</A><DD>
This command concatenates passed arguments and evaluates the
resulting script under the internal mutex protection	. During the
script evaluation, the entire shared variable is locked	. For shared
variable commands within the script, internal locking is disabled
so no deadlock can occur	. It is also allowed to unset the shared
variable from within the script	. The shared variable is automatically
created if it did not exists at the time of the first lock operation	.
<PRE>% tsv::lock foo {
        tsv::lappend foo bar 1
        tsv::lappend foo bar 2
        puts stderr [tsv::set foo bar]
        tsv::unset foo
    }</PRE>
<P><DT><A NAME="M17"><B>tsv::handlers</B></A><DD>
Returns the names of all persistent storage handlers enabled at compile time	.
See <B><A HREF="#M29">ARRAY COMMANDS</A></B> for details	.
<P></DL>
<P>
<H3><A NAME="M18">LIST COMMANDS</A></H3>
Those command are similar to the equivalently named Tcl command	. The difference
is that they operate on elements of shared arrays	.
<P>
<DL class="list commands">
<DT><A NAME="M19"><B>tsv::lappend</B> <I>varname</I> <I>element</I> <I>value</I> ?value 	.	.	.?</A><DD>
Similar to standard Tcl <B><A HREF="../TclCmd/lappend.htm">lappend</A></B> command but appends one
or more values to the <I>element</I> in shared variable <I>varname</I>
instead of the Tcl variable	.
<P><DT><A NAME="M20"><B>tsv::linsert</B> <I>varname</I> <I>element</I> <I>index</I> <I>value</I> ?value 	.	.	.?</A><DD>
Similar to standard Tcl <B><A HREF="../TclCmd/linsert.htm">linsert</A></B> command but inserts one
or more values at the <I>index</I> list position in the
<I>element</I> in the shared variable <I>varname</I> instead of the Tcl variable	.
<P><DT><A NAME="M21"><B>tsv::lreplace</B> <I>varname</I> <I>element</I> <I>first</I> <I>last</I> ?value 	.	.	.?</A><DD>
Similar to standard Tcl <B><A HREF="../TclCmd/lreplace.htm">lreplace</A></B> command but replaces one
or more values between the <I>first</I> and <I>last</I> position
in the <I>element</I> of the shared variable <I>varname</I> instead of
the Tcl variable	.
<P><DT><A NAME="M22"><B>tsv::llength</B> <I>varname</I> <I>element</I></A><DD>
Similar to standard Tcl <B><A HREF="../TclCmd/llength.htm">llength</A></B> command but returns length
of the <I>element</I> in the shared variable <I>varname</I> instead of the Tcl
variable	.
<P><DT><A NAME="M23"><B>tsv::lindex</B> <I>varname</I> <I>element</I> ?index?</A><DD>
Similar to standard Tcl <B><A HREF="../TclCmd/lindex.htm">lindex</A></B> command but returns the value
at the <I>index</I> list position of the <I>element</I> from
the shared variable <I>varname</I> instead of the Tcl variable	.
<P><DT><A NAME="M24"><B>tsv::lrange</B> <I>varname</I> <I>element</I> <I>from</I> <I>to</I></A><DD>
Similar to standard Tcl <B><A HREF="../TclCmd/lrange.htm">lrange</A></B> command but returns values
between <I>from</I> and <I>to</I> list positions from the
<I>element</I> in the shared variable <I>varname</I> instead of the Tcl variable	.
<P><DT><A NAME="M25"><B>tsv::lsearch</B> <I>varname</I> <I>element</I> ?options? <I>pattern</I></A><DD>
Similar to standard Tcl <B><A HREF="../TclCmd/lsearch.htm">lsearch</A></B> command but searches the <I>element</I>
in the shared variable <I>varname</I> instead of the Tcl variable	.
<P><DT><A NAME="M26"><B>tsv::lset</B> <I>varname</I> <I>element</I> <I>index</I> ?index 	.	.	.? <I>value</I></A><DD>
Similar to standard Tcl <B><A HREF="../TclCmd/lset.htm">lset</A></B> command but sets the <I>element</I>
in the shared variable <I>varname</I> instead of the Tcl variable	.
<P><DT><A NAME="M27"><B>tsv::lpop</B> <I>varname</I> <I>element</I> ?index?</A><DD>
Similar to the standard Tcl <B><A HREF="../TclCmd/lindex.htm">lindex</A></B> command but in addition to
returning, it also splices the value out of the <I>element</I>
from the shared variable <I>varname</I> in one atomic operation	.
In contrast to the Tcl <B><A HREF="../TclCmd/lindex.htm">lindex</A></B> command, this command returns
no value to the caller	.
<P><DT><A NAME="M28"><B>tsv::lpush</B> <I>varname</I> <I>element</I> ?index?</A><DD>
This command performes the opposite of the <B>tsv::lpop</B> command	.
As its counterpart, it returns no value to the caller	.
<P></DL>
<P>
<H3><A NAME="M29">ARRAY COMMANDS</A></H3>
This command supports most of the options of the standard Tcl
<B><A HREF="../TclCmd/array.htm">array</A></B> command	. In addition to those, it allows binding
a shared variable to some persisten storage databases	. Currently the persistent
options supported are the famous GNU Gdbm and LMDB	. These options have to be
selected during the package compilation time	.
The implementation provides hooks for defining other persistency layers, if
needed	.
<P>
<DL class="array commands">
<DT><A NAME="M30"><B>tsv::array set</B> <I>varname</I> <I>list</I></A><DD>
Does the same as standard Tcl <B><A HREF="../TclCmd/array.htm">array set</A></B>	.
<P><DT><A NAME="M31"><B>tsv::array get</B> <I>varname</I> ?pattern?</A><DD>
Does the same as standard Tcl <B><A HREF="../TclCmd/array.htm">array get</A></B>	.
<P><DT><A NAME="M32"><B>tsv::array names</B> <I>varname</I> ?pattern?</A><DD>
Does the same as standard Tcl <B><A HREF="../TclCmd/array.htm">array names</A></B>	.
<P><DT><A NAME="M33"><B>tsv::array size</B> <I>varname</I></A><DD>
Does the same as standard Tcl <B><A HREF="../TclCmd/array.htm">array size</A></B>	.
<P><DT><A NAME="M34"><B>tsv::array reset</B> <I>varname</I> <I>list</I></A><DD>
Does the same as standard Tcl <B><A HREF="../TclCmd/array.htm">array set</A></B> but it clears
the <I>varname</I> and sets new values from the list atomically	.
<P><DT><A NAME="M35"><B>tsv::array bind</B> <I>varname</I> <I>handle</I></A><DD>
Binds the <I>varname</I> to the persistent storage <I>handle</I>	.
The format of the <I>handle</I> is &lt;handler&gt;:&lt;address&gt;, where &lt;handler&gt; is
&quot;gdbm&quot; for GNU Gdbm and &quot;lmdb&quot; for LMDB and &lt;address&gt; is the path to the
database file	.
<P><DT><A NAME="M36"><B>tsv::array unbind</B> <I>varname</I></A><DD>
Unbinds the shared <I>array</I> from its bound persistent storage	.
<P><DT><A NAME="M37"><B>tsv::array isbound</B> <I>varname</I></A><DD>
Returns true (1) if the shared <I>varname</I> is bound to some
persistent storage or zero (0) if not	.
<P></DL>
<P>
<H3><A NAME="M38">KEYED LIST COMMANDS</A></H3>
Keyed list commands are borrowed from the TclX package	. Keyed lists provide
a structured data type built upon standard Tcl lists	. This is a functionality
similar to structs in the C programming language	.
<P>
A keyed list is a list in which each element contains a key and value
pair	. These element pairs are stored as lists themselves, where the key
is the first element of the list, and the value is the second	. The
key-value pairs are referred to as fields	.  This is an example of a
keyed list:
<PRE>{{NAME  {Frank  Zappa}} {JOB {musician and composer}}}</PRE>
Fields may contain subfields; `	.' is the separator character	. Subfields
are actually fields  where the value is another keyed list	. Thus the
following list has the top level fields ID and NAME, and subfields
NAME	.FIRST and NAME	.LAST:
<PRE>{ID 106} {NAME {{FIRST Frank} {LAST Zappa}}}</PRE>
There is no limit to the recursive depth of subfields,
allowing one to build complex data structures	. Keyed lists are constructed
and accessed via a number of commands	. All  keyed  list management
commands take the name of the variable containing the keyed list as an
argument (i	.e	. passed by reference), rather than passing the list directly	.
<P>
<DL class="keyed list commands">
<DT><A NAME="M39"><B>tsv::keyldel</B> <I>varname</I> <I>keylist</I> <I>key</I></A><DD>
Delete the field specified by <I>key</I> from the keyed list <I>keylist</I>
in the shared variable <I>varname</I>	.
This removes both the key and the value from the keyed list	.
<P><DT><A NAME="M40"><B>tsv::keylget</B> <I>varname</I> <I>keylist</I> <I>key</I> ?retvar?</A><DD>
Return the value associated with <I>key</I> from the keyed list <I>keylist</I>
in the shared variable <I>varname</I>	.
If the optional <I>retvar</I> is not specified, then the value will be
returned as the result of the command	. In this case, if key is not found
in the list, an error will result	.
<P>
If <I>retvar</I> is specified and <I>key</I> is in the list, then the value
is returned in the variable <I>retvar</I> and the command returns 1 if the
key was present within the list	. If <I>key</I> isn't in the list, the
command will return 0, and <I>retvar</I> will be left unchanged	. If {} is
specified for <I>retvar</I>, the value is not returned, allowing the Tcl
programmer to determine if a <I>key</I> is present in a keyed list without
setting a variable as a side-effect	.
<P><DT><A NAME="M41"><B>tsv::keylkeys</B> <I>varname</I> <I>keylist</I> ?key?</A><DD>
Return  the a list of the keys in the keyed list <I>keylist</I> in the
shared variable <I>varname</I>	. If <I>key</I> is specified, then it is
the name of a key field who's subfield keys are to be retrieved	.
<P><DT><A NAME="M42"><B>tsv::keylset</B> <I>varname</I> <I>keylist</I> <I>key</I> <I>value</I> ?key value	.	.?</A><DD>
Set the value associated with <I>key</I>, in the keyed list <I>keylist</I>
to <I>value</I>	. If the <I>keylist</I> does not exists, it is created	.
If <I>key</I> is not currently in the list, it will be added	. If it already
exists, <I>value</I> replaces the existing value	. Multiple keywords and
values may be specified, if desired	.
<P></DL>
<P>
<H3><A NAME="M43">DISCUSSION</A></H3>
The current implementation of thread shared variables allows for easy and
convenient access to data shared between different threads	.
Internally, the data is stored in Tcl objects and all package commands
operate on internal data representation, thus minimizing shimmering and
improving performance	. Special care has been taken to assure that all
object data is properly locked and deep-copied when moving objects between
threads	.
<P>
Due to the internal design of the Tcl core, there is no provision of full
integration of shared variables within the Tcl syntax, unfortunately	. All
access to shared data must be performed with the supplied package commands	.
Also, variable traces are not supported	. But even so, benefits of easy,
simple and safe shared data manipulation outweights imposed limitations	.
<H3><A NAME="M44">CREDITS</A></H3>
Thread shared variables are inspired by the nsv interface found in
AOLserver, a highly scalable Web server from America Online	.
<H3><A NAME="M45">SEE ALSO</A></H3>
<B><A HREF="../ThreadCmd/thread.htm">thread</A></B>, <B><A HREF="../ThreadCmd/tpool.htm">tpool</A></B>, <B><A HREF="../ThreadCmd/ttrace.htm">ttrace</A></B>
<H3><A NAME="M46">KEYWORDS</A></H3>
<A href="../Keywords/L.htm#locking">locking</A>, <A href="../Keywords/S.htm#synchronization">synchronization</A>, <A href="../Keywords/T.htm#thread shared data">thread shared data</A>, <A href="../Keywords/T.htm#threads">threads</A>
<div class="copy"></div>
</BODY></HTML>
